$mac!(generate_lockfile);
$mac!(git_checkout);
$mac!(help);
+ $mac!(init);
$mac!(install);
$mac!(locate_project);
$mac!(login);
--- /dev/null
+use std::env;
+
+use cargo::ops;
+use cargo::util::{CliResult, Config};
+
+#[derive(RustcDecodable)]
+struct Options {
+ flag_verbose: bool,
+ flag_quiet: bool,
+ flag_color: Option<String>,
+ flag_bin: bool,
+ arg_path: Option<String>,
+ flag_name: Option<String>,
+ flag_vcs: Option<ops::VersionControl>,
+}
+
+pub const USAGE: &'static str = "
+Create a new cargo package in current directory
+
+Usage:
+ cargo init [options] [<path>]
+ cargo init -h | --help
+
+Options:
+ -h, --help Print this message
+ --vcs VCS Initialize a new repository for the given version
+ control system (git or hg) or do not initialize any version
+ control at all (none) overriding a global configuration.
+ --bin Use a binary instead of a library template
+ --name NAME Set the resulting package name
+ -v, --verbose Use verbose output
+ -q, --quiet No output printed to stdout
+ --color WHEN Coloring: auto, always, never
+";
+
+pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
+ debug!("executing; cmd=cargo-init; args={:?}", env::args().collect::<Vec<_>>());
+ try!(config.shell().set_verbosity(options.flag_verbose, options.flag_quiet));
+ try!(config.shell().set_color_config(options.flag_color.as_ref().map(|s| &s[..])));
+
+ let Options { flag_bin, arg_path, flag_name, flag_vcs, .. } = options;
+
+ let opts = ops::NewOptions {
+ version_control: flag_vcs,
+ bin: flag_bin,
+ path: &arg_path.unwrap_or(format!(".")),
+ name: flag_name.as_ref().map(|s| s.as_ref()),
+ };
+
+ try!(ops::init(opts, config));
+ Ok(None)
+}
+
use std::fs;
use std::io::prelude::*;
use std::path::Path;
+use std::collections::BTreeMap;
use rustc_serialize::{Decodable, Decoder};
pub name: Option<&'a str>,
}
+struct SourceFileInformation {
+ relative_path: String,
+ target_name: String,
+ bin: bool,
+}
+
+struct MkOptions<'a> {
+ version_control: Option<VersionControl>,
+ path: &'a Path,
+ name: &'a str,
+ source_files: Vec<SourceFileInformation>,
+}
+
impl Decodable for VersionControl {
fn decode<D: Decoder>(d: &mut D) -> Result<VersionControl, D::Error> {
Ok(match &try!(d.read_str())[..] {
version_control: Option<VersionControl>,
}
-pub fn new(opts: NewOptions, config: &Config) -> CargoResult<()> {
- let path = config.cwd().join(opts.path);
- if fs::metadata(&path).is_ok() {
- bail!("destination `{}` already exists", path.display())
+fn get_name<'a>(path: &'a Path, opts: &'a NewOptions, config: &Config) -> CargoResult<&'a str> {
+ if let Some(name) = opts.name {
+ return Ok(name);
}
- let name = match opts.name {
- Some(name) => name,
- None => {
- let dir_name = try!(path.file_name().and_then(|s| s.to_str()).chain_error(|| {
- human(&format!("cannot create a project with a non-unicode name: {:?}",
- path.file_name().unwrap()))
- }));
- if opts.bin {
- dir_name
- } else {
- let new_name = strip_rust_affixes(dir_name);
- if new_name != dir_name {
- let message = format!(
- "note: package will be named `{}`; use --name to override",
- new_name);
- try!(config.shell().say(&message, BLACK));
- }
- new_name
- }
+
+ if path.file_name().is_none() {
+ bail!("cannot auto-detect project name from path {:?} ; use --name to override",
+ path.as_os_str());
+ }
+
+ let dir_name = try!(path.file_name().and_then(|s| s.to_str()).chain_error(|| {
+ human(&format!("cannot create a project with a non-unicode name: {:?}",
+ path.file_name().unwrap()))
+ }));
+
+ if opts.bin {
+ Ok(dir_name)
+ } else {
+ let new_name = strip_rust_affixes(dir_name);
+ if new_name != dir_name {
+ let message = format!(
+ "note: package will be named `{}`; use --name to override",
+ new_name);
+ try!(config.shell().say(&message, BLACK));
}
- };
+ Ok(new_name)
+ }
+}
+
+fn check_name(name: &str) -> CargoResult<()> {
for c in name.chars() {
if c.is_alphanumeric() { continue }
if c == '_' || c == '-' { continue }
- bail!("Invalid character `{}` in crate name: `{}`", c, name)
+ bail!("Invalid character `{}` in crate name: `{}`\n\
+ use --name to override crate name",
+ c, name)
+ }
+ Ok(())
+}
+
+fn detect_source_paths_and_types(project_path : &Path,
+ project_name: &str,
+ detected_files: &mut Vec<SourceFileInformation>,
+ ) -> CargoResult<()> {
+ let path = project_path;
+ let name = project_name;
+
+ enum H {
+ Bin,
+ Lib,
+ Detect,
+ }
+
+ struct Test {
+ proposed_path: String,
+ handling: H,
+ }
+
+ let tests = vec![
+ Test { proposed_path: format!("src/main.rs"), handling: H::Bin },
+ Test { proposed_path: format!("main.rs"), handling: H::Bin },
+ Test { proposed_path: format!("src/{}.rs", name), handling: H::Detect },
+ Test { proposed_path: format!("{}.rs", name), handling: H::Detect },
+ Test { proposed_path: format!("src/lib.rs"), handling: H::Lib },
+ Test { proposed_path: format!("lib.rs"), handling: H::Lib },
+ ];
+
+ for i in tests {
+ let pp = i.proposed_path;
+
+ // path/pp does not exist or is not a file
+ if !fs::metadata(&path.join(&pp)).map(|x| x.is_file()).unwrap_or(false) {
+ continue;
+ }
+
+ let sfi = match i.handling {
+ H::Bin => {
+ SourceFileInformation {
+ relative_path: pp,
+ target_name: project_name.to_string(),
+ bin: true
+ }
+ }
+ H::Lib => {
+ SourceFileInformation {
+ relative_path: pp,
+ target_name: project_name.to_string(),
+ bin: false
+ }
+ }
+ H::Detect => {
+ let content = try!(paths::read(&path.join(pp.clone())));
+ let isbin = content.contains("fn main");
+ SourceFileInformation {
+ relative_path: pp,
+ target_name: project_name.to_string(),
+ bin: isbin
+ }
+ }
+ };
+ detected_files.push(sfi);
+ }
+
+ // Check for duplicate lib attempt
+
+ let mut previous_lib_relpath : Option<&str> = None;
+ let mut duplicates_checker : BTreeMap<&str, &SourceFileInformation> = BTreeMap::new();
+
+ for i in detected_files {
+ if i.bin {
+ if let Some(x) = BTreeMap::get::<str>(&duplicates_checker, i.target_name.as_ref()) {
+ bail!("\
+multiple possible binary sources found:
+ {}
+ {}
+cannot automatically generate Cargo.toml as the main target would be ambiguous",
+ &x.relative_path, &i.relative_path);
+ }
+ duplicates_checker.insert(i.target_name.as_ref(), i);
+ } else {
+ if let Some(plp) = previous_lib_relpath {
+ return Err(human(format!("cannot have a project with \
+ multiple libraries, \
+ found both `{}` and `{}`",
+ plp, i.relative_path)));
+ }
+ previous_lib_relpath = Some(&i.relative_path);
+ }
+ }
+
+ Ok(())
+}
+
+fn plan_new_source_file(bin: bool, project_name: String) -> SourceFileInformation {
+ if bin {
+ SourceFileInformation {
+ relative_path: "src/main.rs".to_string(),
+ target_name: project_name,
+ bin: true,
+ }
+ } else {
+ SourceFileInformation {
+ relative_path: "src/lib.rs".to_string(),
+ target_name: project_name,
+ bin: false,
+ }
}
- mk(config, &path, name, &opts).chain_error(|| {
+}
+
+pub fn new(opts: NewOptions, config: &Config) -> CargoResult<()> {
+ let path = config.cwd().join(opts.path);
+ if fs::metadata(&path).is_ok() {
+ bail!("destination `{}` already exists",
+ path.display())
+ }
+
+ let name = try!(get_name(&path, &opts, config));
+ try!(check_name(name));
+
+ let mkopts = MkOptions {
+ version_control: opts.version_control,
+ path: &path,
+ name: name,
+ source_files: vec![plan_new_source_file(opts.bin, name.to_string())],
+ };
+
+ mk(config, &mkopts).chain_error(|| {
+ human(format!("Failed to create project `{}` at `{}`",
+ name, path.display()))
+ })
+}
+
+pub fn init(opts: NewOptions, config: &Config) -> CargoResult<()> {
+ let path = config.cwd().join(opts.path);
+
+ let cargotoml_path = path.join("Cargo.toml");
+ if fs::metadata(&cargotoml_path).is_ok() {
+ bail!("`cargo init` cannot be run on existing Cargo projects")
+ }
+
+ let name = try!(get_name(&path, &opts, config));
+ try!(check_name(name));
+
+ let mut src_paths_types = vec![];
+
+ try!(detect_source_paths_and_types(&path, name, &mut src_paths_types));
+
+ if src_paths_types.len() == 0 {
+ src_paths_types.push(plan_new_source_file(opts.bin, name.to_string()));
+ } else {
+ // --bin option may be ignored if lib.rs or src/lib.rs present
+ // Maybe when doing `cargo init --bin` inside a library project stub,
+ // user may mean "initialize for library, but also add binary target"
+ }
+
+ let mut version_control = opts.version_control;
+
+ if version_control == None {
+ let mut num_detected_vsces = 0;
+
+ if fs::metadata(&path.join(".git")).is_ok() {
+ version_control = Some(VersionControl::Git);
+ num_detected_vsces += 1;
+ }
+
+ if fs::metadata(&path.join(".hg")).is_ok() {
+ version_control = Some(VersionControl::Hg);
+ num_detected_vsces += 1;
+ }
+
+ // if none exists, maybe create git, like in `cargo new`
+
+ if num_detected_vsces > 1 {
+ bail!("both .git and .hg directories found \
+ and the ignore file can't be \
+ filled in as a result, \
+ specify --vcs to override detection");
+ }
+ }
+
+ let mkopts = MkOptions {
+ version_control: version_control,
+ path: &path,
+ name: name,
+ source_files: src_paths_types,
+ };
+
+ mk(config, &mkopts).chain_error(|| {
human(format!("Failed to create project `{}` at `{}`",
name, path.display()))
})
GitRepo::discover(path, cwd).is_ok() || HgRepo::discover(path, cwd).is_ok()
}
-fn mk(config: &Config, path: &Path, name: &str,
- opts: &NewOptions) -> CargoResult<()> {
+fn mk(config: &Config, opts: &MkOptions) -> CargoResult<()> {
+ let path = opts.path;
+ let name = opts.name;
let cfg = try!(global_config(config));
let mut ignore = "target\n".to_string();
let in_existing_vcs_repo = existing_vcs_repo(path.parent().unwrap(), config.cwd());
- if !opts.bin {
- ignore.push_str("Cargo.lock\n");
- }
+ ignore.push_str("Cargo.lock\n");
let vcs = match (opts.version_control, cfg.version_control, in_existing_vcs_repo) {
(None, None, false) => VersionControl::Git,
match vcs {
VersionControl::Git => {
- try!(GitRepo::init(path, config.cwd()));
- try!(paths::write(&path.join(".gitignore"), ignore.as_bytes()));
+ if !fs::metadata(&path.join(".git")).is_ok() {
+ try!(GitRepo::init(path, config.cwd()));
+ }
+ try!(paths::append(&path.join(".gitignore"), ignore.as_bytes()));
},
VersionControl::Hg => {
- try!(HgRepo::init(path, config.cwd()));
- try!(paths::write(&path.join(".hgignore"), ignore.as_bytes()));
+ if !fs::metadata(&path.join(".hg")).is_ok() {
+ try!(HgRepo::init(path, config.cwd()));
+ }
+ try!(paths::append(&path.join(".hgignore"), ignore.as_bytes()));
},
VersionControl::NoVcs => {
- try!(fs::create_dir(path));
+ try!(fs::create_dir_all(path));
},
};
(Some(name), None, _, None) |
(None, None, name, None) => name,
};
+
+ let mut cargotoml_path_specifier = String::new();
+
+ // Calculare what [lib] and [[bin]]s do we need to append to Cargo.toml
+
+ for i in &opts.source_files {
+ if i.bin {
+ if i.relative_path != "src/main.rs" {
+ cargotoml_path_specifier.push_str(&format!(r#"
+[[bin]]
+name = "{}"
+path = {}
+"#, i.target_name, toml::Value::String(i.relative_path.clone())));
+ }
+ } else {
+ if i.relative_path != "src/lib.rs" {
+ cargotoml_path_specifier.push_str(&format!(r#"
+[lib]
+name = "{}"
+path = {}
+"#, i.target_name, toml::Value::String(i.relative_path.clone())));
+ }
+ }
+ }
+
+ // Create Cargo.toml file with necessary [lib] and [[bin]] sections, if needed
try!(paths::write(&path.join("Cargo.toml"), format!(
r#"[package]
authors = [{}]
[dependencies]
-"#, name, toml::Value::String(author)).as_bytes()));
+{}"#, name, toml::Value::String(author), cargotoml_path_specifier).as_bytes()));
- try!(fs::create_dir(&path.join("src")));
- if opts.bin {
- try!(paths::write(&path.join("src/main.rs"), b"\
+ // Create all specified source files
+ // (with respective parent directories)
+ // if they are don't exist
+
+ for i in &opts.source_files {
+ let path_of_source_file = path.join(i.relative_path.clone());
+
+ if let Some(src_dir) = path_of_source_file.parent() {
+ try!(fs::create_dir_all(src_dir));
+ }
+
+ let default_file_content : &[u8] = if i.bin {
+ b"\
fn main() {
println!(\"Hello, world!\");
}
-"));
- } else {
- try!(paths::write(&path.join("src/lib.rs"), b"\
+"
+ } else {
+ b"\
#[cfg(test)]
mod test {
#[test]
fn it_works() {
}
}
-"));
+"
+ };
+
+ if !fs::metadata(&path_of_source_file).map(|x| x.is_file()).unwrap_or(false) {
+ return paths::write(&path_of_source_file, default_file_content)
+ }
}
Ok(())
pub use self::cargo_rustc::{CommandType, CommandPrototype, ExecEngine, ProcessEngine};
pub use self::cargo_run::run;
pub use self::cargo_install::{install, install_list, uninstall};
-pub use self::cargo_new::{new, NewOptions, VersionControl};
+pub use self::cargo_new::{new, init, NewOptions, VersionControl};
pub use self::cargo_doc::{doc, DocOptions};
pub use self::cargo_generate_lockfile::{generate_lockfile};
pub use self::cargo_generate_lockfile::{update_lockfile};
use std::env;
use std::ffi::{OsStr, OsString};
use std::fs::File;
+use std::fs::OpenOptions;
use std::io::prelude::*;
use std::path::{Path, PathBuf, Component};
})
}
+pub fn append(path: &Path, contents: &[u8]) -> CargoResult<()> {
+ (|| -> CargoResult<()> {
+ let mut f = try!(OpenOptions::new()
+ .write(true)
+ .append(true)
+ .create(true)
+ .open(path));
+
+ try!(f.write_all(contents));
+ Ok(())
+ }).chain_error(|| {
+ internal(format!("failed to write `{}`", path.display()))
+ })
+}
+
#[cfg(unix)]
pub fn path2bytes(path: &Path) -> CargoResult<&[u8]> {
use std::os::unix::prelude::*;
--- /dev/null
+use std::fs::{self, File};
+use std::io::prelude::*;
+use std::env;
+use tempdir::TempDir;
+use support::{execs, paths, cargo_dir};
+use hamcrest::{assert_that, existing_file, existing_dir, is_not};
+
+use cargo::util::{process, ProcessBuilder};
+
+fn setup() {
+}
+
+fn cargo_process(s: &str) -> ProcessBuilder {
+ let mut p = process(&cargo_dir().join("cargo"));
+ p.arg(s).cwd(&paths::root()).env("HOME", &paths::home());
+ return p;
+}
+
+test!(simple_lib {
+ assert_that(cargo_process("init").arg("--vcs").arg("none")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+ assert_that(&paths::root().join("Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("src/lib.rs"), existing_file());
+ assert_that(&paths::root().join(".gitignore"), is_not(existing_file()));
+
+ assert_that(cargo_process("build"),
+ execs().with_status(0));
+});
+
+test!(simple_bin {
+ let path = paths::root().join("foo");
+ fs::create_dir(&path).unwrap();
+ assert_that(cargo_process("init").arg("--bin").arg("--vcs").arg("none")
+ .env("USER", "foo").cwd(&path),
+ execs().with_status(0));
+
+ assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("foo/src/main.rs"), existing_file());
+
+ assert_that(cargo_process("build").cwd(&path),
+ execs().with_status(0));
+ assert_that(&paths::root().join(&format!("foo/target/debug/foo{}",
+ env::consts::EXE_SUFFIX)),
+ existing_file());
+});
+
+fn bin_already_exists(explicit: bool, rellocation: &str) {
+ let path = paths::root().join("foo");
+ fs::create_dir_all(&path.join("src")).unwrap();
+
+ let sourcefile_path = path.join(rellocation);
+
+ let content = br#"
+ fn main() {
+ println!("Hello, world 2!");
+ }
+ "#;
+
+ File::create(&sourcefile_path).unwrap().write_all(content).unwrap();
+
+ if explicit {
+ assert_that(cargo_process("init").arg("--bin").arg("--vcs").arg("none")
+ .env("USER", "foo").cwd(&path),
+ execs().with_status(0));
+ } else {
+ assert_that(cargo_process("init").arg("--vcs").arg("none")
+ .env("USER", "foo").cwd(&path),
+ execs().with_status(0));
+ }
+
+ assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("foo/src/lib.rs"), is_not(existing_file()));
+
+ // Check that our file is not overwritten
+ let mut new_content = Vec::new();
+ File::open(&sourcefile_path).unwrap().read_to_end(&mut new_content).unwrap();
+ assert_eq!(Vec::from(content as &[u8]), new_content);
+}
+
+test!(bin_already_exists_explicit {
+ bin_already_exists(true, "src/main.rs")
+});
+
+test!(bin_already_exists_implicit {
+ bin_already_exists(false, "src/main.rs")
+});
+
+test!(bin_already_exists_explicit_nosrc {
+ bin_already_exists(true, "main.rs")
+});
+
+test!(bin_already_exists_implicit_nosrc {
+ bin_already_exists(false, "main.rs")
+});
+
+test!(bin_already_exists_implicit_namenosrc {
+ bin_already_exists(false, "foo.rs")
+});
+
+test!(bin_already_exists_implicit_namesrc {
+ bin_already_exists(false, "src/foo.rs")
+});
+
+test!(confused_by_multiple_lib_files {
+ let path = paths::root().join("foo");
+ fs::create_dir_all(&path.join("src")).unwrap();
+
+ let sourcefile_path1 = path.join("src/lib.rs");
+
+ File::create(&sourcefile_path1).unwrap().write_all(br#"
+ fn qqq () {
+ println!("Hello, world 2!");
+ }
+ "#).unwrap();
+
+ let sourcefile_path2 = path.join("lib.rs");
+
+ File::create(&sourcefile_path2).unwrap().write_all(br#"
+ fn qqq () {
+ println!("Hello, world 3!");
+ }
+ "#).unwrap();
+
+ assert_that(cargo_process("init").arg("--vcs").arg("none")
+ .env("USER", "foo").cwd(&path),
+ execs().with_status(101).with_stderr("\
+cannot have a project with multiple libraries, found both `src/lib.rs` and `lib.rs`
+"));
+
+ assert_that(&paths::root().join("foo/Cargo.toml"), is_not(existing_file()));
+});
+
+
+test!(multibin_project_name_clash {
+ let path = paths::root().join("foo");
+ fs::create_dir(&path).unwrap();
+
+ let sourcefile_path1 = path.join("foo.rs");
+
+ File::create(&sourcefile_path1).unwrap().write_all(br#"
+ fn main () {
+ println!("Hello, world 2!");
+ }
+ "#).unwrap();
+
+ let sourcefile_path2 = path.join("main.rs");
+
+ File::create(&sourcefile_path2).unwrap().write_all(br#"
+ fn main () {
+ println!("Hello, world 3!");
+ }
+ "#).unwrap();
+
+ assert_that(cargo_process("init").arg("--vcs").arg("none")
+ .env("USER", "foo").cwd(&path),
+ execs().with_status(101).with_stderr("\
+multiple possible binary sources found:
+ main.rs
+ foo.rs
+cannot automatically generate Cargo.toml as the main target would be ambiguous
+"));
+
+ assert_that(&paths::root().join("foo/Cargo.toml"), is_not(existing_file()));
+});
+
+fn lib_already_exists(rellocation: &str) {
+ let path = paths::root().join("foo");
+ fs::create_dir_all(&path.join("src")).unwrap();
+
+ let sourcefile_path = path.join(rellocation);
+
+ let content = br#"
+ pub fn qqq() {}
+ "#;
+
+ File::create(&sourcefile_path).unwrap().write_all(content).unwrap();
+
+ assert_that(cargo_process("init").arg("--vcs").arg("none")
+ .env("USER", "foo").cwd(&path),
+ execs().with_status(0));
+
+ assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("foo/src/main.rs"), is_not(existing_file()));
+
+ // Check that our file is not overwritten
+ let mut new_content = Vec::new();
+ File::open(&sourcefile_path).unwrap().read_to_end(&mut new_content).unwrap();
+ assert_eq!(Vec::from(content as &[u8]), new_content);
+}
+
+test!(lib_already_exists_src {
+ lib_already_exists("src/lib.rs")
+});
+
+test!(lib_already_exists_nosrc {
+ lib_already_exists("lib.rs")
+});
+
+test!(simple_git {
+ assert_that(cargo_process("init").arg("--vcs").arg("git")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+ assert_that(&paths::root().join("Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("src/lib.rs"), existing_file());
+ assert_that(&paths::root().join(".git"), existing_dir());
+ assert_that(&paths::root().join(".gitignore"), existing_file());
+});
+
+test!(auto_git {
+ let td = TempDir::new("cargo").unwrap();
+ let foo = &td.path().join("foo");
+ fs::create_dir_all(&foo).unwrap();
+ assert_that(cargo_process("init").cwd(foo.clone())
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+ assert_that(&foo.join("Cargo.toml"), existing_file());
+ assert_that(&foo.join("src/lib.rs"), existing_file());
+ assert_that(&foo.join(".git"), existing_dir());
+ assert_that(&foo.join(".gitignore"), existing_file());
+});
+
+test!(invalid_dir_name {
+ let foo = &paths::root().join("foo.bar");
+ fs::create_dir_all(&foo).unwrap();
+ assert_that(cargo_process("init").cwd(foo.clone())
+ .env("USER", "foo"),
+ execs().with_status(101).with_stderr("\
+Invalid character `.` in crate name: `foo.bar`
+use --name to override crate name
+"));
+
+ assert_that(&foo.join("Cargo.toml"), is_not(existing_file()));
+});
+
+test!(git_autodetect {
+ fs::create_dir(&paths::root().join(".git")).unwrap();
+
+ assert_that(cargo_process("init")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+
+ assert_that(&paths::root().join("Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("src/lib.rs"), existing_file());
+ assert_that(&paths::root().join(".git"), existing_dir());
+ assert_that(&paths::root().join(".gitignore"), existing_file());
+});
+
+
+test!(mercurial_autodetect {
+ fs::create_dir(&paths::root().join(".hg")).unwrap();
+
+ assert_that(cargo_process("init")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+
+ assert_that(&paths::root().join("Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("src/lib.rs"), existing_file());
+ assert_that(&paths::root().join(".git"), is_not(existing_dir()));
+ assert_that(&paths::root().join(".hgignore"), existing_file());
+});
+
+test!(gitignore_appended_not_replaced {
+ fs::create_dir(&paths::root().join(".git")).unwrap();
+
+ File::create(&paths::root().join(".gitignore")).unwrap().write_all(b"qqqqqq\n").unwrap();
+
+ assert_that(cargo_process("init")
+ .env("USER", "foo"),
+ execs().with_status(0));
+
+
+ assert_that(&paths::root().join("Cargo.toml"), existing_file());
+ assert_that(&paths::root().join("src/lib.rs"), existing_file());
+ assert_that(&paths::root().join(".git"), existing_dir());
+ assert_that(&paths::root().join(".gitignore"), existing_file());
+
+ let mut contents = String::new();
+ File::open(&paths::root().join(".gitignore")).unwrap().read_to_string(&mut contents).unwrap();
+ assert!(contents.contains(r#"qqqqqq"#));
+});
+
+test!(with_argument {
+ assert_that(cargo_process("init").arg("foo").arg("--vcs").arg("none")
+ .env("USER", "foo"),
+ execs().with_status(0));
+ assert_that(&paths::root().join("foo/Cargo.toml"), existing_file());
+});
+
+
+test!(unknown_flags {
+ assert_that(cargo_process("init").arg("foo").arg("--flag"),
+ execs().with_status(1)
+ .with_stderr("\
+Unknown flag: '--flag'
+
+Usage:
+ cargo init [options] [<path>]
+ cargo init -h | --help
+"));
+});
+
+#[cfg(not(windows))]
+test!(no_filename {
+ assert_that(cargo_process("init").arg("/"),
+ execs().with_status(101)
+ .with_stderr("\
+cannot auto-detect project name from path \"/\" ; use --name to override
+"));
+});
test!(invalid_characters {
assert_that(cargo_process("new").arg("foo.rs"),
execs().with_status(101)
- .with_stderr("Invalid character `.` in crate name: `foo.rs`"));
+ .with_stderr("\
+Invalid character `.` in crate name: `foo.rs`
+use --name to override crate name"));
});
test!(rust_prefix_stripped {
mod test_cargo_fetch;
mod test_cargo_freshness;
mod test_cargo_generate_lockfile;
+mod test_cargo_init;
mod test_cargo_install;
mod test_cargo_new;
mod test_cargo_package;